home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Commun⁄Network / RevRdist Folder / RevRdist / RevRdist src / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-08  |  12.8 KB  |  571 lines  |  [TEXT/KAHL]

  1. /*
  2.  * init.c - initialization routines
  3.  */
  4. #include "RevRdist.h"
  5. #include <GestaltEqu.h>
  6. #include "TransSkelProto.h"
  7. #include "TransDisplayProto.h"
  8. #include "desktop.h"
  9. #include <Finder.h>
  10. #include <Errors.h>
  11. #include <AppleEvents.h>
  12.  
  13. extern unsigned char ApplScratch[12] : 0xA78;
  14.  
  15. /*
  16.  * prototypes for functions in AppleEvents.c
  17.  */
  18. OSErr    DoHighLevelEvent (EventRecord *theEvent);
  19. OSErr    init_AppleEvent(Boolean);
  20.  
  21. void    checkRun(void);
  22. void    checkVersion(void);
  23. OSErr    get_launch_args (void);
  24. void    quitOthers(void);
  25.  
  26.  
  27.  
  28. /*
  29.  *=========================================================================
  30.  * checkRun - check if we should run now
  31.  * entry:    File_list[FL_PREF], Prefs[P_WORK] set
  32.  * exit:    Quit = true if application must quit immediately
  33.  *=========================================================================
  34.  */
  35. void
  36. checkRun (void)
  37. {
  38.     file_info_t        *fi;            /* ptr in File_list */
  39.     unsigned long    now, atime;    /* for time calcs */
  40.     prefs_t            *pi;
  41.  
  42.     /*
  43.      * If not running automatically, make no decision
  44.      */
  45.     if (!(Flags & PF_STARTUP))
  46.         return;
  47.     GetDateTime (&now);
  48.     /*
  49.      * Check if update interval being observed and it is not time yet
  50.      */
  51.     if (Flags & PF_TOUCH)
  52.     {
  53.         fi = &File_list[FL_PREF];
  54.         pi = &Prefs[P_WORK];
  55.         if (fi->f_set)
  56.         {
  57.             atime = fi->f_info.mdDate + pi->p_interval;
  58.             if (now < atime)
  59.             {
  60.                 Quit = 1;
  61.             }
  62.         }
  63.     }
  64. }
  65.  
  66.  
  67.  
  68. /*
  69.  *=========================================================================
  70.  * checkVersion - check if we are an old version and a newer version is
  71.  *                present
  72.  * entry:    File_list[FL_APPL] filled in
  73.  * exit:    Quit = true if application must quit immediately
  74.  *=========================================================================
  75.  */
  76. void
  77. checkVersion (void)
  78. {
  79.     OSErr            error;
  80.     file_info_t        *fi;            /* ptr in File_list */
  81.     int                idx;            /* for scanning folder */
  82.     unsigned long    mdDate;            /* our mod time */
  83.     Longint            parID;            /* our parent folder */
  84.     Integer            vol;            /* our vRefNum */
  85.     CInfoPBRec        ci;
  86.     Str255            name;
  87.  
  88.     /*
  89.      * Check for another copy of us in the same folder.
  90.      * If present and newer, quit.
  91.      */
  92.     fi = &File_list[FL_APPL];
  93.     vol = fi->f_vol;
  94.     parID = fi->f_info.parID;
  95.     mdDate = fi->f_info.mdDate;
  96.     ZERO(ci);
  97.     ci.hFileInfo.ioNamePtr = name;
  98.     for (idx = 1; ; idx++)
  99.     {
  100.         name[0] = 0;
  101.         ci.hFileInfo.ioVRefNum = vol;
  102.         ci.hFileInfo.ioFDirIndex = idx;
  103.         ci.hFileInfo.ioDirID = parID;
  104.         error = PBGetCatInfo (&ci, false);
  105.         if (error)
  106.             break;
  107.         if ((ci.hFileInfo.ioFlAttrib & ioDirMask) == 0
  108.          && ci.hFileInfo.ioFlFndrInfo.fdCreator == CREATOR
  109.          && ci.hFileInfo.ioFlFndrInfo.fdType == 'APPL'
  110.          && ci.hFileInfo.ioFlMdDat > mdDate)
  111.         {
  112.             FlashMenuBar(0);
  113.             Quit = 1;
  114.             break;
  115.         }
  116.     }
  117. }
  118.  
  119.  
  120.  
  121.  
  122. /*
  123.  *=========================================================================
  124.  * initGlobals - set up the (too many) global variables
  125.  * exit:    Quit = false if initialization succeeded
  126.  *            Quit = true if application must quit immediately
  127.  *=========================================================================
  128.  */
  129. void
  130. initGlobals ()
  131. {
  132.     OSErr            error;
  133.     file_info_t *    fi;                    /* ptr into File_list[] */
  134.     Handle            h;                    /* temp handle */
  135.     long *            lp;                    /* ptr into ApplScratch */
  136.     StringHandle    sh;                    /* temp string handle */
  137.     SysEnvRec        theWorld;            /* environment info */
  138.     WindowPtr        w;                    /* working window pointer */
  139.     WDPBRec            wdpb;                /* to get boot volume */
  140.     Str255            pname;                /* prefs file name */
  141.  
  142.     HighValue[0] = 3;
  143.     HighValue[1] = HighValue[2] = HighValue[3] = 255;
  144.     Clue0 = "\pinitGlobals";
  145.     Quit = false;
  146.     Ap_refNum = CurResFile ();
  147.     error = SysEnvirons (1, &theWorld);
  148.     if (error)
  149.     {
  150.         Quit = true;
  151.         return;
  152.     }
  153.     BlessedWD = theWorld.sysVRefNum;
  154.     ZERO (wdpb);
  155.     wdpb.ioVRefNum = BlessedWD;
  156.     error = PBGetWDInfo (&wdpb, false);
  157.     if (error)
  158.     {
  159.         Quit = true;
  160.         return;
  161.     }
  162.     /*
  163.      * Make sure we are running under HFS
  164.      */
  165.     if (FSFCBLen < 0)
  166.     {
  167.         panic (true, E_HFS, CurApName, nil);
  168.         return;
  169.     }
  170.     BootVol = wdpb.ioWDVRefNum;
  171.     /*
  172.      * Allocate File_list and insert info about Application
  173.      */
  174.     File_list = (file_info_t *) NewPtr (FL_MAX * sizeof (* File_list));
  175.     if (!File_list)
  176.         goto nomem;
  177.     memset ((char *)File_list, 0, FL_MAX * sizeof (* File_list));
  178.  
  179.     fi = &File_list[FL_APPL];
  180.     fi->f_ref = Ap_refNum;
  181.     fi->f_info.ctype = C_FILE;
  182.     if (error = getInfoByPath ("\p", fi))
  183.         goto sysdie;
  184.     fi->f_launch = true;
  185.  
  186.     /*
  187.      * Set processing flag bits
  188.      * Check ApplScratch for our signature to see if
  189.      * we are running automatically at boot time.
  190.      * That works if we were started by RevRINIT.
  191.      * We might also start because we are in the Startup Items folder.
  192.      * Check for that also.
  193.      */
  194.     Flags = 0;
  195.     h = Get1Resource (TYPE_LONG, FLAG_PARM);
  196.     if (h)
  197.     {
  198.         Flags = **((long **)h);
  199.         ReleaseResource (h);
  200.     }
  201.     lp = (long *)(ApplScratch + 8);
  202.     if (lp[0] == CREATOR)
  203.     {
  204.         Flags |= PF_STARTUP;
  205.         lp[0] = 0;
  206.     }
  207.     if (!(Flags & PF_STARTUP))
  208.     {
  209.         Longint        lt;
  210.         Integer        itemp;
  211.  
  212.         error = TickCount() > 3 * 60 * 60;        /* within 3 min of start up ? */
  213.         if (!error)
  214.             error = Gestalt(gestaltFindFolderAttr, <);
  215.         if (!error)
  216.             error = !(lt & (1<<gestaltFindFolderPresent));
  217.         if (!error)
  218.             error = FindFolder (BootVol, 'strt', kDontCreateFolder, &itemp, <);
  219.         if (!error && (lt == fi->f_info.parID))
  220.             Flags |= PF_STARTUP;
  221.         error = 0;
  222.     }
  223.     /*
  224.      * Test if we are old version
  225.      */
  226.     if (Flags & PF_STARTUP)
  227.         checkVersion();
  228.     if (Quit)
  229.     {
  230.         Flags &= ~PF_RESTART;
  231.         return;                        /* yes, exit now without reboot */
  232.     }
  233.     /*
  234.      * Continue filling in File_list with
  235.      *    info about any files passed as parameters
  236.      */
  237.     error = get_launch_args();
  238.     if (error)
  239.         goto sysdie;
  240.     /*
  241.      * Bring up flags dialog if selected
  242.      */
  243.     if ((Flags & PF_DIALOG) || ((Flags & PF_LOCKED) == 0 && Button()))
  244.         setFlags ();
  245.     else if ((Flags & (PF_STARTUP|PF_FINDUPD)) == (PF_STARTUP|PF_FINDUPD))
  246.     {
  247.         int    i;
  248.         EventRecord    theEvent;
  249.         /*
  250.          * We need a dummy event loop here to give AppleShare time to start up
  251.          */
  252.         for (i = 0; i < 4; i++)
  253.         {
  254.             if (WaitNextEvent(everyEvent, &theEvent, 60, nil))
  255.             {
  256.                 switch (theEvent.what)
  257.                 {
  258.                 }
  259.             }
  260.         }
  261.     }
  262.     if (Quit)
  263.         return;
  264.     ActivityWind = GetNewDWindow (RSRC_BASE+WIND_ACTIVITY, (WindowPtr) -1L);
  265.     ErrorWind = GetNewDWindow (RSRC_BASE+WIND_ERRORS, (WindowPtr) -1L);
  266.     SetDWindow (ActivityWind);
  267.     /*
  268.      * Get junking renaming suffix
  269.      */
  270.     h = GetResource ('STR ', STR_JUNKSUF);
  271.     if (!h || **h > sizeof (Junksuf) - 1 || **h < 2)
  272.     {
  273.         panic (true, E_BADJUNKF, nil);
  274.         return;
  275.     }
  276.     COPYPS (*h, Junksuf);
  277.     ReleaseResource (h);
  278.     /*
  279.      * Get name for anonymous documents
  280.      */
  281.     h = GetResource ('STR ', STR_UNTITLED);
  282.     if (!h)
  283.     {
  284.         error = ResError ();
  285.         goto sysdie;
  286.     }
  287.     Untitled = (StringHandle) h;
  288.     /*
  289.      * Get names for temp files
  290.      */
  291.     h = GetResource ('STR ', STR_TEMP1);
  292.     if (!h || **h > sizeof (TempName) - 1 || **h < 2)
  293.     {
  294.         panic (true, E_BADTEMPF, nil);
  295.         return;
  296.     }
  297.     COPYPS (*h, TempName);
  298.     ReleaseResource (h);
  299.     h = GetResource ('STR ', STR_TEMP2);
  300.     if (!h || **h > sizeof (TempName2) - 1 || **h < 2)
  301.     {
  302.         panic (true, E_BADTEMPF, nil);
  303.         return;
  304.     }
  305.     COPYPS (*h, TempName2);
  306.     ReleaseResource (h);
  307.     /*
  308.      * Initialize preferences from application
  309.      */
  310.     memset ((char *)&Prefs[0], 0, 2 * sizeof (prefs_t));
  311.     if (prefFetch (File_list[FL_APPL].f_ref) == 0)
  312.         prefMerge (P_WORK, false);
  313.     /*
  314.      * Load preferences from file.
  315.      * If we haven't located a preferences file yet, try finding the one
  316.      * given by the preferences string within the application.
  317.      * It's not a problem if we cannot find the file.
  318.      */
  319.     error = 0;
  320.     fi = &File_list[FL_PREF];
  321.     if (fi->f_set)
  322.     {
  323.         COPYPS(fi->f_info.name, pname);    /* save name for msg */
  324.         error = prefFFetch (fi);
  325.     }
  326.     else
  327.     {
  328.         sh = (StringHandle) GetResource ('STR ', STR_PREFS);
  329.         if (!sh)
  330.         {
  331.             panic (true, E_SYS, Clue0,
  332.                 "\pGetResource", "\ppref file name");
  333.             return;
  334.         }
  335.         COPYPS (*sh, pname);
  336.         ReleaseResource ((Handle) sh);
  337.         fi->f_vol = 0;
  338.         fi->f_ref = 0;
  339.         error = getInfoByPath (pname, fi);
  340.         if (error == 0)
  341.             error = prefFFetch (fi);
  342.     }
  343.     if (error == 0)
  344.         prefMerge (P_WORK, true);
  345.     Prefs[P_WORK].p_modified = false;
  346.     if (error)
  347.     {
  348.         /*
  349.          * Tell about no prefs
  350.          * If not startup, see if we should continue.
  351.          */
  352.         panic (Flags & PF_STARTUP, E_PREFS, pname, nil);
  353.         if (Quit && (Flags & PF_STARTUP))
  354.             Flags &= ~PF_RESTART;    /* avoid reboot loop */
  355.     }
  356.     if (Quit)
  357.         return;
  358.     checkRun();                    /* see if time to run */
  359.     if (Quit)
  360.     {
  361.         Flags &= ~PF_RESTART;    /* not time, let sys come up */
  362.         return;
  363.     }
  364.     /*
  365.      * Kill off other processes if requested
  366.      */
  367.     if (Flags & PF_QUITOTHERS)
  368.         quitOthers();
  369.     return;
  370.  
  371. sysdie:
  372.     ClueID = error;
  373.     panic (true, E_SYS, Clue0, nil);
  374.     Quit = true;
  375.     return;
  376.  
  377. nomem:
  378.     SysBeep (5);
  379.     Quit = true;
  380.     return;
  381. }
  382.  
  383.  
  384.  
  385. /*
  386.  *=========================================================================
  387.  * get_launch_args () - find out why we were launched
  388.  *  That is, get any files used to start us
  389.  * returns    OSErr
  390.  *        File_list[] possibly modified
  391.  *=========================================================================
  392.  */
  393. OSErr
  394. get_launch_args(void)
  395. {
  396.     OSErr            error;
  397.     Integer            fcount, fmsg;    /* Finder args */
  398.     int                i;
  399.     file_info_t        *fi;            /* ptr into File_list */
  400.     Longint            lp;
  401.     EventRecord        theEvent;
  402.  
  403.     /*
  404.      * Check if Apple Event are supported.
  405.      * If not, get files the old, simple way.
  406.      * Otherwise, use kludgy code to get the Apple events which give
  407.      * us the file info
  408.      */
  409.     lp = 0;
  410.     error = Gestalt (gestaltAppleEventsAttr, &lp);
  411.     if (error || (lp & (1<<gestaltAppleEventsPresent)) == 0)
  412.     {
  413.         /*
  414.          * Hurray!  No Apple events to contend with
  415.          */
  416.         error = 0;
  417.         CountAppFiles (&fmsg, &fcount);
  418.         if (fmsg == 1 && fcount > 0)
  419.         {
  420.             panic (false, E_NOPRINT, nil);
  421.             if (Quit)
  422.                 return;
  423.         }
  424.  
  425.         Ap_file.fType = 0;
  426.         for (i = 1; i <= fcount; i++)
  427.         {
  428.             int    j;
  429.  
  430.             GetAppFiles (i, &Ap_file);
  431.             switch (Ap_file.fType)
  432.             {
  433.             case TYPE_PREF: j = FL_PREF; break;
  434.             case TYPE_CONT:    j = FL_DIST; break;
  435.             case 'INIT':    j = -1; Flags |= PF_STARTUP; break;
  436.             default:        j = -1; break;
  437.             }
  438.             if (j >= 0)
  439.             {
  440.                 fi = &File_list[j];
  441.                 fi->f_vol = Ap_file.vRefNum;
  442.                 error = getInfoByPath (Ap_file.fName, fi);
  443.                 if (error == 0)
  444.                     fi->f_launch = true;
  445.             }
  446.             ClrAppFiles (i);
  447.         }
  448.         return error;
  449.     }
  450.     /*
  451.      * Ugh!  Use a dummy event loop to give the system time to send
  452.      * us the events which started us
  453.      */
  454.     error = init_AppleEvent(true);
  455.     for (i = 0; i < 100; i++)
  456.     {
  457.         if (WaitNextEvent(everyEvent, &theEvent, 0, nil))
  458.         {
  459.             switch (theEvent.what)
  460.             {
  461.             case kHighLevelEvent:
  462.                 i = 100;
  463.                 error = DoHighLevelEvent(&theEvent);
  464.                 break;
  465.             }
  466.         }
  467.     }
  468.     (void) init_AppleEvent(false);    /* remove handlers */
  469.     return error;
  470. }
  471.  
  472.  
  473.  
  474. /*
  475.  *=========================================================================
  476.  * quitOthers () - try to cause other applications to quit
  477.  *=========================================================================
  478.  */
  479. void
  480. quitOthers (void)
  481. {
  482.     OSErr                    error;
  483.     OSType                    theType;    /* process file type */
  484.     OSType                    theSig;        /* process signature */
  485.     Longint                    lp;            /* for Gestalt */
  486.     unsigned long            ticks;        /* the ticks */
  487.     int                        gotone;        /* true if signaled a process */
  488.     ProcessSerialNumber        process;
  489.     ProcessInfoRec            inforec;
  490.     FSSpec                    fsspec;
  491.     Str31                    pname;        /* process name */
  492.     AEDesc                    target;
  493.     AppleEvent                theEvent;
  494.     EventRecord                event;        /* for WaitNextEvent() */
  495.  
  496.     /*
  497.      * Check for process manager.
  498.      * Give up if not present
  499.      */
  500.     error = Gestalt(gestaltOSAttr, &lp);
  501.     if (error)
  502.         return;
  503.     if (!(lp & (1<<gestaltLaunchControl)))
  504.         return;
  505.     for (ticks = TickCount() + 30*60, gotone = 1; gotone && TickCount() < ticks;)
  506.     {
  507.         gotone = 0;
  508.         /*
  509.          * Scan running processes
  510.          */
  511.         ZERO (process);
  512.         ZERO (theEvent);
  513.         ZERO (target);
  514.         ZERO (inforec);
  515.         process.lowLongOfPSN = kNoProcess;
  516.  
  517.         inforec.processInfoLength = sizeof(inforec);
  518.         inforec.processName = pname;
  519.         inforec.processAppSpec = &fsspec;
  520.  
  521.         do
  522.         {
  523.             error = GetNextProcess(&process);
  524.             if (error == 0)
  525.                 error = GetProcessInformation (&process, &inforec);
  526.             if (error == 0)
  527.             {
  528.                 theSig = inforec.processSignature;
  529.                 theType = inforec.processType;
  530.                 /*
  531.                  * Try to quit Finder, applications, and desk accessories
  532.                  */
  533.                 if ( (theSig == 'MACS' && theType == 'FNDR')
  534.                 ||   (theType == 'APPL' && theSig != CREATOR)
  535.                 ||     (inforec.processMode & modeDeskAccessory)
  536.                 )
  537.                 {
  538.                     error = AECreateDesc (typeProcessSerialNumber,
  539.                             (Ptr)&process, sizeof (process),
  540.                             &target);
  541.                     if (error == 0)
  542.                         error = AECreateAppleEvent (kCoreEventClass, kAEQuitApplication,
  543.                             &target, kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
  544.                     if (error == 0)
  545.                         error = AESend (&theEvent, nil, kAENoReply,
  546.                             kAENormalPriority, kNoTimeOut, nil, nil);
  547.                     if (error == 0)
  548.                         gotone = 1;
  549.                     error = 0;
  550.                     AEDisposeDesc(&theEvent);
  551.                     AEDisposeDesc(&target);
  552.                 }
  553.             }
  554.         } while (error == 0);
  555.         if (gotone)
  556.             (void) WaitNextEvent(everyEvent, &event, 20, nil);
  557.     }
  558. }
  559.  
  560.  
  561. /*
  562.  *=========================================================================
  563.  * tidyUp () - do final cleanup before exiting
  564.  *=========================================================================
  565.  */
  566. void
  567. tidyUp ()
  568. {
  569.     desktop_end();
  570. }
  571.